#include "sortcg.h"
#include "io.h"
#include "hop_sort.h"

int
sortcg(GLBVAL *glb)
{
	int 	spos;
	int 	freeblk;
	BLOCKARRS **slink;
	
	slink = (BLOCKARRS **) glb->slink;
	
	if (!(glb->flags & GLBRUNINSEC)) {
		if ((freeblk = find_freeblk(glb)) <= 0) {
			fprintf(stderr, "Can not find free blok for temporary saving.\n");
			return 1;
		}
	}
	
	for (spos = 0; spos < glb->slink_size && slink[spos]; spos++) {
		
		/* blok je jiz na svem miste */
		if (slink[spos]->blkdest == slink[spos]->apindx)
			continue;
		
		/* typ razeni */
		if (glb->flags & GLBRUNINSEC) {
			if (hop_sort(glb, spos))
				return 1;
		}
		else {
			if (triple_sort(glb, spos, freeblk))
				return 1;
		}
	}

	return 0;
}




/*
 * najde prvni volny blok
 * nehleda na aktualnim cg
 * hleda co nejblize aktualnimu cg
 */
int
find_freeblk(GLBVAL *glb)
{
	int 	up;
	int 	down;
	int		freeblk = -1;
	struct cg *acg;
	
	acg = glb->acg;
	
	down = acg->cg_cgx - 1;
	up = acg->cg_cgx + 1;
	
	while (down >= 0 || up < afs.fs_ncg) {
		if (down >= 0) {
			freeblk = find_freeblk_cg (glb, down);
			if (freeblk > 0)
				break;
		}
			
		if (up < afs.fs_ncg) {
			freeblk = find_freeblk_cg (glb, up);
			if (freeblk > 0) {
				break;
			}
		}

		down--;
		up++;
	}
		
	return freeblk;
}

/*
 * prohleda cylinder a vrati cislo volneho bloku
 */
int
find_freeblk_cg (GLBVAL *glb, int cgx)
{
	char 	*blkmap;
	int 	i,j;
	int 	stop;
	int		freeblk = -1;
	
	cgun 	aacg;
	struct cg *scg;
	scg = (struct cg *) &(aacg.cg);
		
	
	if (read_cgblock(glb, &scg, cgx)) {
		warn ("Can not read cylinder number %d", cgx);
		return -1;
	}
	
	blkmap = (char *) cg_blksfree(scg);
	
	/* skok na pocatek datovy oblasti v konkretnim cg */
	i = cgtod(&afs, cgx) - cgstart(&afs, cgx);

	stop = scg->cg_ndblk;
	
	while (i < stop) {
		j = 0;
		
		/* kontrola, zda jsou vsechny frag v bloky free */
		for (j = 0; j < afs.fs_frag; j++) {
			if (isclr(blkmap, i+j))
				break;
		}
		
		if (afs.fs_frag == j) {
			freeblk = i + cgstart(&afs, cgx);
			assert ((freeblk % afs.fs_frag) == 0); 
			break;
		}
		else {
			i += afs.fs_frag;
		}
	}
	
	return freeblk;
}

/* 
 * swp source, nastavi ino a apindx do swp
 */
int
prepare_swp_src(GLBVAL *glb, SWPDATA *swpsrc, int spos) 
{
	ino_t 	ino;
	uint	blkindx;
	struct cg *acg;
	BLOCKARRS **slink;
	BLOCKARRS *ap;
	
	slink = (BLOCKARRS ** ) (glb->slink);
	acg = glb->acg;
	
	ap = slink[spos];
	ino = ap->ino;
	blkindx = ap->blkindx;
	
	swpsrc->ino = ino; 
	swpsrc->apindx = ap->apindx;
	
	if (prepare_swp(glb, ino, blkindx, swpsrc) == 1) {
		fprintf(stderr, "Prepare swp src error\n");
		return 1;
	}

	return 0;
}

/* 
 * swp destination 
 */
int
prepare_swp_dest(GLBVAL *glb, SWPDATA *swpsrc, SWPDATA *swpdest, BLOCKARRS *apout) 
{
	int 	fd;
	int 	bpossrc;
	int 	bposdest;
	uint	apdestindx;
	BLOCKARRS *apsrc;
	BLOCKARRS *apdest;
	BLOCKARRS **blockap;
	struct cg 	*acg;
	
	blockap = (BLOCKARRS **) glb->blockap;
	
	fd = glb->fd;
	acg = glb->acg;
	
	/* ap neni docasne mimo blockap */
	if (apout == NULL) {
		assert(blockap[swpsrc->apindx]);
		apsrc = blockap[swpsrc->apindx];
	}
	else {
		apsrc = apout;
	}
	
	/* vzdy by melo byt zmapovane */
	assert(apsrc);
		
	apdestindx = apsrc->blkdest;
	apdest = blockap[apdestindx];
	swpdest->apindx = apdestindx;
	
	/* umistim blok do volneho bloku XXX */
	if (apdest == NULL) {
		swpdest->flags = ZERODESTINO;
		
		/* pocet bloku do aktualniho cylindru + akt offset */
		/* swpdest->addr = acg->cg_cgx * acg->cg_ndblk + swpdest->apindx * afs.fs_frag; */
	}
	else {
		swpdest->ino = apdest->ino;				
		
		/* flag nastavim jiz zde */
		if (apdest->blkindx < NDADDR)
			swpdest->flags = SWPDB;
		else
			swpdest->flags = SWPIB;		
		
		/* swpdest->blkindx = recount_blkindx(apdest->blkindx); */
		
		/* musim kouknout, jestli nesaham na stejny ib blok, pokud ano, tak pouziju stejny buffer */
		if ((swpsrc->flags & SWPIB) && (swpdest->flags & SWPIB)) {
			bpossrc = (int) ((apsrc->blkindx - NDADDR)/NINDIRS);
			bposdest = (int) ((apdest->blkindx - NDADDR)/NINDIRS);
		}
		
		/* 
		 * bud ukazuju na stejny buf, nebo si dest nacte vlastni
		 * 
		 * Podminka:
		 * odkazy na oba bloky jsou prime (DB) a soucasne bloky inodu jsou stejne
		 * nebo
		 * dva bloky z jednoho inodu ze stejneho ib bloku
		 */
		if (((ino_to_fsba(&afs, swpsrc->ino) == ino_to_fsba(&afs, swpdest->ino)) &&
			(swpsrc->flags & SWPDB) && (swpdest->flags & SWPDB)) ||
			(swpsrc->ino == swpdest->ino && bpossrc == bposdest &&
			(swpsrc->flags & SWPIB) && (swpdest->flags & SWPIB))
			) {
			
			swpdest->buf = swpsrc->buf;
			swpdest->addr = swpsrc->addr;
			swpdest->blkindx = recount_blkindx(apdest->blkindx);
		}
		else {
			if (prepare_swp(glb, apdest->ino, apdest->blkindx, swpdest) == 1) {
				fprintf(stderr, "Prepare swp dest error\n");
				return 1;			
			}
		}
	}
	
	return 0;
}

/* 
 * prepocita abs hodnotu indexu, na relativni hodnotu vuci 
 * ib bloku na kterem jsou data umistena
 */
int
recount_blkindx(int indx)
{
	int ret = 0;
	
	if (indx < NDADDR) {
		ret = indx;
	} 
	else {
		ret = (indx - NDADDR) % NINDIRS;
	}
	
	return ret;
}

/* 
 * ziskam ib blok, pokud je primy odkaz, tak se nacte oblast inodu na data 
 * 
 * nastavi ino, blkindx, flags, buf, addr 
 */
int
prepare_swp(GLBVAL *glb, ino_t ino, int indx, SWPDATA *swp)
{
	int 	st_buftmp[MAXBSIZE];
	char	st_inobuf[MAXBSIZE];
	int 	*buftmp;
	char	*inobuf;
	int		indxtmp;
	off_t	offset;
	struct ufs1_dinode *dptmp;
	
	inobuf = st_inobuf;
	read_inodes_block(glb, (void **) &inobuf, ino);
	dptmp = &(((struct ufs1_dinode *) inobuf)[ino_to_fsbo(&afs, ino)]);
	
	if (indx < NDADDR) {
		swp->blkindx = recount_blkindx(indx);
		swp->flags = SWPDB;
		
		/* 
		 * rovnaji-li se, oblast inodu se kopiroval do inobuf z disku
		 * nerovnaji-li se, inobuf ukazuje do oblasti mmapu
		 */
		if (inobuf == st_inobuf)
			memcpy(swp->buf, inobuf, MAXBSIZE);
		else
			swp->buf = inobuf;
			
		if (dptmp->di_db[swp->blkindx] == 0)
			return 1;
		
	}
	else if (indx < (NINDIRS + NDADDR)) {
		swp->blkindx = recount_blkindx(indx);
		swp->flags = SWPIB;
		swp->addr = dptmp->di_ib[0];
		
		offset = dptmp->di_ib[0];
		
		if (read_fs_block(glb, (void **) &(swp->buf), offset)) {
			fprintf(stderr, "Prepare swap error\n");
			return 1;	
		}
			
		if (((int*)(swp->buf))[swp->blkindx] == 0) {
			fprintf(stderr, "Prepare swap error\n");
			return 1;			
		}
			
	} 
	else if (indx < ((NINDIRS * NINDIRS) + NDADDR)) {
		swp->blkindx = recount_blkindx(indx);
		swp->flags = SWPIB;
		
		offset = dptmp->di_ib[1];
		
		buftmp = st_buftmp;
		if (read_fs_block(glb, (void **) &buftmp, offset)) {
			fprintf(stderr, "Prepare swap error\n");
			return 1;
		}
			
		indxtmp = (int) (((indx - NDADDR) - NINDIRS) / NINDIRS);
		offset = buftmp[indxtmp];
		swp->addr = offset;
		
		if (read_fs_block(glb, (void **) &(swp->buf), offset)) {
			fprintf(stderr, "Prepare swap error\n");
			return 1;
		}
			
		if (((int*)(swp->buf))[swp->blkindx] == 0) {
			fprintf(stderr, "Prepare swap error\n");
			return 1;				
		}
								
	}
	/* XXX Neotestovano - soubor o 256 GB. */
	else {
		swp->blkindx = recount_blkindx(indx);
		swp->flags = SWPIB;
		
		/* 1st */
		offset = dptmp->di_ib[2];
		buftmp = st_buftmp;
		if (read_fs_block(glb, (void **) &buftmp, offset)) {
			fprintf(stderr, "Prepare swap error\n");
			return 1;
		}
		
		/* 2nd */	
		indxtmp = (int) (((indx - NDADDR) - NINDIRS) / NINDIRS);
		offset = buftmp[indxtmp];
		buftmp = st_buftmp;
		if (read_fs_block(glb, (void **) &buftmp, offset)) {
			fprintf(stderr, "Prepare swap error\n");
			return 1;
		}
		
		/* 3rd */
		indxtmp = (int) ((((indx - NDADDR) - NINDIRS) - (NINDIRS * NINDIRS)) / NINDIRS);
		offset = buftmp[indxtmp];
		swp->addr = offset;
		if (read_fs_block(glb, (void **) &(swp->buf), offset)) {
			fprintf(stderr, "Prepare swap error\n");
			return 1;
		}
				
		if (((int*)(swp->buf))[swp->blkindx] == 0) {
			fprintf(stderr, "Prepare swap error\n");
			return 1;	
		}
	}
	

	return 0;
}

/*
 * Nastavi bity v bitmape bloku.
 * Free bloky jsou nastaveny v bitmape na 1.
 * Vstup je fs blok.
 * chyba = 1; ok = 0
 */
int
cgbitmap_set(GLBVAL *glb, uint blkindx)
{
	uint	j;
	uint	sent;
	char	*bmap;
	
	bmap = (char *) cg_blksfree(glb->acg);
	
	/* musim vzit relativne k aktualknimu cg */
	blkindx = blkindx % (glb->acg)->cg_ndblk;
	sent = blkindx + afs.fs_frag;
	
	for (j = blkindx; j < sent; j++) {
#if DEBUG
		assert(isclr(bmap, j));
#endif
		setbit(bmap, j);
	}	
	
	/*
	if (write_cgblock(glb) == 1)
		return 1;
	*/
	
	return 0;
}

/*
 * Vynuluje bity v bitmape bloku.
 * Obsazene bloky jsou nastaveny v bitmape na 0.
 * Vstup je fs blok.
 * chyba = 1; ok = 0
 */
int
cgbitmap_clr(GLBVAL *glb, uint blkindx)
{
	uint	j;
	uint	sent;
	char	*bmap;
	
	bmap = (char *) cg_blksfree(glb->acg);
	
	/* musim vzit relativne k aktualknimu cg */
	blkindx = blkindx % (glb->acg)->cg_ndblk;
	sent = blkindx + afs.fs_frag;
	
	for (j = blkindx; j < sent; j++) {
#if DEBUG
		assert(isset(bmap, j));
#endif
		clrbit(bmap, j);
	}
	
	/*
	if (write_cgblock(glb) == 1)
		return 1;
	*/
	return 0;
}


int
get_dest_blk(GLBVAL *glb, SWPDATA *swp)
{
	uint 	destindx;
	BLOCKARRS **blockap;
	
	blockap = (BLOCKARRS **) glb->blockap;
	
	if (blockap[swp->apindx])
		destindx = blockap[swp->apindx]->blkdest;
	else
		return 0;
	
	if (blockap[destindx] == NULL)
		return destindx;
	else
		return 0;
}

/*
 * Nacte a ulozi blok z adr v swp na blkdest.
 * Vraci pozici bloku, z ktere se presouvalo.
 * SWAP_ERR = chyba
 */
uint
swap_block (GLBVAL *glb, SWPDATA *swp, uint blkdest) 
{
	uint	blksrc;
	char	st_buf[MAXBSIZE];
	char	*buf;
	struct ufs1_dinode	*dp;	

	/* Vypocet adresy pro blok */
	/* src */
	if (swp->flags & SWPDB) {
		dp = &(((struct ufs1_dinode *) swp->buf)[ino_to_fsbo(&afs, swp->ino)]);
		blksrc = dp->di_db[swp->blkindx];
	}
	else {
		blksrc = ((int *)(swp->buf))[swp->blkindx];
	}
	
	/* Presun bloku */
	buf = st_buf;
	if (read_fs_block(glb, (void **) &buf, blksrc)) {
		fprintf(stderr, "move blk read error (addr %d)", blksrc);
		return SWAP_ERR;
	}
		
	if (write_fs_block(glb, buf, blkdest)) {
		fprintf(stderr, "move blk write error (addr %d)", blkdest);
		return SWAP_ERR;
	}
			
	return blksrc;
}

/*
 * Ulozi do inodu/indir bloku adresu na blok.
 * Pro zachovani navrat hodnot s swap_block:
 * SWAP_ERR = chyba
 */ 
int
swap_inode (GLBVAL *glb, SWPDATA *swp, uint blkdest) 
{
	struct ufs1_dinode	*dp;
	uint 	addr;	

	/* Zmena v inodu */
	if (swp->flags & SWPDB) {
		dp = &(((struct ufs1_dinode *) swp->buf)[ino_to_fsbo(&afs, swp->ino)]);
		dp->di_db[swp->blkindx] = blkdest;
	}
	else {
		((int *)(swp->buf))[swp->blkindx] = blkdest;	
	}
	
	/* zapis do oblasti inodu(db) / ib block */
	if (swp->flags & SWPDB) {
		if (write_inodes_block(glb, swp->buf, swp->ino)) {
			fprintf(stderr, "write inodes block (ino %d)", swp->ino);
			return SWAP_ERR;
		}
	}
	else {
		addr = swp->addr;
		
		if (write_fs_block(glb, swp->buf, addr)) {
			fprintf(stderr, "write ib block (addr %d)", swp->addr);
			return SWAP_ERR;
		}
	}
		
	return SWAP_OK;
}

/*
 * Vraci adresu noveho tmp bloku, nebo 0  (= chyba)
 */
uint
swap_src_p1(GLBVAL *glb, SWPDATA *swp)
{
	uint 	destindx;	/* ukazatel na volnou pozici (relativne k cg) */
	uint	blkdest;	/* ukazatel na volny blk (abs adr) */
	uint 	newfreeblk;
	BLOCKARRS **blockap;
	
	blockap = (BLOCKARRS **) glb->blockap;
	
	
	/* 
	 * Dest jiz musi byt volny, jinake nekde nastala chyba. 
	 */
	destindx = get_dest_blk(glb, swp);
	if (destindx > 0) {
		blkdest = indxtoblk(glb, destindx);
	}
	else {
		fprintf(stderr, "Dest block is not free: (ino: %d, apindx: %d)\n",
			swp->ino, swp->apindx);
		return SWPSRCERR;
	}
	
	/* swap bloku */
	newfreeblk = swap_block (glb, swp, blkdest);
	if (newfreeblk == SWAP_ERR)
		return SWPSRCERR;
	
	/* swap inodu */
	if (swap_inode (glb, swp, blkdest) == SWAP_ERR)
		return SWPSRCERR;
	
	blockap[destindx] = blockap[swp->apindx];
	blockap[destindx]->apindx = destindx;
	blockap[swp->apindx] = NULL;
	
	return newfreeblk;
}

/*
 * Vraci flag 
 * - bud je moje pozice prazdna
 * - nebo cilova pozice je prazdna
 */
int
swap_dest_p1(GLBVAL *glb, SWPDATA *swp, BLOCKARRS **aptmp, int freeblk)
{
	uint 	destapindx;	/* ukazatel na volnou pozici (relativne k cg) */
	uint	blkdest;	/* ukazatel na volny blk (abs adr) */
	uint8_t flag;       /* byl/nebyl cilovy blk volny */
	BLOCKARRS **blockap;
	
	flag = SWPDESTOK;
	blockap = (BLOCKARRS **) glb->blockap;
	
	/* pozice dest neni obsazena */
	if (blockap[swp->apindx] == NULL) {
		/* XXX nastavit bitmapu */
		/* na tohle misto pujde src */
		blkdest = indxtoblk(glb, swp->apindx); 
		cgbitmap_clr(glb, blkdest);
		return SWPDESTEMPTY;
	}
	
	/*
	 * Dest se bud presune na docasne misto do freeblk, nebo do jeho budouci
	 * pozice. je jiz volna a vlozi se primo do ni.
	 * musim nastavit bitmapu
	 */
	destapindx = get_dest_blk(glb, swp);
	if (destapindx > 0) {
		flag = SWPDESTONPLACE;
		blkdest = indxtoblk(glb, destapindx); 
		
		/* dest jde na neobsazenou pozici */
		cgbitmap_clr(glb, blkdest);
	}
	else 
		blkdest = freeblk;
	
	
	/* swap bloku */
	if (swap_block (glb, swp, blkdest) == SWAP_ERR)
		return SWPDESTERR;	
	
	/* swap inodu */
	if (swap_inode (glb, swp, blkdest) == SWAP_ERR)
		return SWPDESTERR;	
		
	/* 
	 * blockap pole
	 */
	if (flag == SWPDESTONPLACE) {
		blockap[destapindx] = blockap[swp->apindx];
		blockap[destapindx]->apindx = destapindx;
		blockap[swp->apindx] = NULL;
	}
	else {
		*aptmp = blockap[swp->apindx];
		blockap[swp->apindx] = NULL;
	}
	
	return flag;
}

/*
 * Src byl v tmp bloku
 * Vraci SWPSRCERR nebo SWPSRCOK
 */
uint
swap_src_p2(GLBVAL *glb, SWPDATA *swp, BLOCKARRS *aptmp)
{
	uint 	destindx;	/* ukazatel na volnou pozici (relativne k cg) */
	uint	blkdest;	/* ukazatel na volny blk (abs adr) */
	BLOCKARRS **blockap;
	
	blockap = (BLOCKARRS **) glb->blockap;
	
	if (aptmp) {
		destindx = aptmp->blkdest;
		blkdest = indxtoblk(glb, destindx); 
	}
	else {
		fprintf(stderr, "Dest block can not be reached.\n");
		return SWPSRCERR;
	}
	
	/* swap bloku */
	if (swap_block (glb, swp, blkdest) == SWAP_ERR)
		return SWPSRCERR;	
	
	/* swap inodu */
	if (swap_inode (glb, swp, blkdest) == SWAP_ERR)
		return SWPSRCERR;

	blockap[destindx] = aptmp;
	blockap[destindx]->apindx = destindx;
	
	return SWPSRCOK;
}

int
swap_dest_p2(GLBVAL *glb, SWPDATA *swp, int freeblk)
{
	uint 	destindx;	/* ukazatel na volnou pozici (relativne k cg) */
	uint	blkdest;	/* ukazatel na volny blk (abs adr) */
	uint8_t flag; 		/* byl/nebyl cilovy blk volny */
	uint	apindx;
	BLOCKARRS **blockap;
	
	flag = SWPDESTOK;
	blockap = (BLOCKARRS **) glb->blockap;

	/* muze nastat pouze pokud byl na zacatku vzajemny swap dvou bloku */
	if (blockap[swp->apindx] == NULL) {
		return SWPDESTONPLACE;
	}	

	/*
	 * Dest se bud presune na docasne misto do freeblk, nebo do jeho budouci
	 * pozice. je jiz volna a vlozi se primo do ni.
	 * musim nastavit bitmapu
	 */
	destindx = get_dest_blk(glb, swp);
	if (destindx > 0) {
		flag = SWPDESTONPLACE;
		blkdest = indxtoblk(glb, destindx);
		
		if (blkdest != freeblk) {
			cgbitmap_clr(glb, blkdest);
			cgbitmap_set(glb, freeblk);
		}
	}
	else 
		blkdest = freeblk;
	
	/* swap bloku */
	if (swap_block (glb, swp, blkdest) == SWAP_ERR)
		return SWPDESTERR;	
	
	/* swap inodu */
	if (swap_inode (glb, swp, blkdest) == SWAP_ERR)
		return SWPDESTERR;	
		
	/* 
	 * blockap pole
	 */
	if (flag == SWPDESTONPLACE) {
		blockap[destindx] = blockap[swp->apindx];
		blockap[destindx]->apindx = destindx;
		blockap[swp->apindx] = NULL;
	}
	else {
		apindx = blktoindx(glb, blkdest);
		assert (blockap[apindx] == NULL);
		blockap[apindx] = blockap[swp->apindx];
		blockap[apindx]->apindx = apindx;
		blockap[swp->apindx] = NULL;

		swp->apindx = apindx;
	}
	
	return flag;
}

void
bind_swpdata_mem (SWPDATA *swpsrc, SWPDATA *swpdest, int *mem1, int *mem2)
{
	if (swpsrc->buf == (void *) mem1)
		swpdest->buf = (void *) mem2;
	else
		swpdest->buf = (void *) mem1;
}


int
triple_sort(GLBVAL *glb, int spos, int freeblk)
{
	int 		freeblktmp;
	int			bufsrc[MAXBSIZE];
	int			bufdest[MAXBSIZE];
	int 		ret;
	SWPDATA 	*swpsrc;
	SWPDATA 	*swpdest;
	SWPDATA 	*swptmp;
	BLOCKARRS 	*aptmp;
	BLOCKARRS	**blockap;
	
	blockap = (BLOCKARRS**)glb->blockap;
	
	swpsrc = (SWPDATA *) malloc (sizeof(SWPDATA));
	swpdest = (SWPDATA *) malloc (sizeof(SWPDATA));
	if (swpsrc == NULL || swpdest == NULL) {
		warn("Malloc error in sort");
		return 1;
	}
	
	bzero (swpsrc, sizeof(SWPDATA));
	swpsrc->buf = (void *) bufsrc;
	
	ret = prepare_swp_src (glb, swpsrc, spos);
	if (ret)
		return 1;

	do {
		bzero (swpdest, sizeof(SWPDATA));
		bind_swpdata_mem(swpsrc, swpdest, bufsrc, bufdest);
		ret = prepare_swp_dest (glb, swpsrc, swpdest, NULL);
		if (ret)
			return 1;
			
		/* 
		 * FAZE 1 
		 */
		aptmp = NULL;
		ret = swap_dest_p1(glb, swpdest, &aptmp, freeblk);
		freeblktmp = swap_src_p1(glb, swpsrc);
		
		/* nastala chyba */
		if (freeblktmp == SWPSRCERR)
			break;
			
		if (ret == SWPDESTERR)
			return 1;
			
		
		/* 
		 * oba dva bloky jsou na cilovych mistech 
		 * faze 2 netreba
		 */
		if (ret == SWPDESTEMPTY || ret == SWPDESTONPLACE) {
			cgbitmap_set(glb, indxtoblk(glb, swpsrc->apindx));
			break;
		}
					
		/* 
		 * Faze 2 
		 */
		swptmp = swpsrc;
		swpsrc = swpdest;
		swpdest = swptmp;

		bzero (swpdest, sizeof(SWPDATA));
		bind_swpdata_mem(swpsrc, swpdest, bufsrc, bufdest);
		ret = prepare_swp_dest (glb, swpsrc, swpdest, aptmp);
		if (ret)
			return 1;
		
		ret = swap_dest_p2(glb, swpdest, freeblktmp);
		if (ret == SWPDESTERR)
			return 1;		
		
		if (swap_src_p2(glb, swpsrc, aptmp) == SWPSRCERR)
			return 1;
		
	
		/* src/dest swap */
		swptmp = swpsrc;
		swpsrc = swpdest;
		swpdest = swptmp;

	} while (ret != SWPDESTONPLACE);
	
	
	/* neukladam cg (bitmapu) po kazde zmene, fsck ji umi opravit */
	if (write_cgblock(glb) == 1)
		return 1;	
	
	free(swpsrc);
	free(swpdest);

	return 0;
	
}
